package com.miracle.service.impl;

import com.miracle.dao.OrderDAO;
import com.miracle.dao.StockDAO;
import com.miracle.dao.UserDAO;
import com.miracle.entity.Order;
import com.miracle.entity.Stock;
import com.miracle.entity.User;
import com.miracle.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * OrderService实现类
 * @author jie.xi
 * @date 2022年04月20日 10:16
 */

@Service
@Transactional
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    StockDAO stockDAO;

    @Autowired
    OrderDAO orderDAO;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    UserDAO userDAO;

    @Override
    public int kill(Integer id) {
        //检验redis中秒杀商品是否超时
        if(!stringRedisTemplate.hasKey("kill"+id)){
            throw new RuntimeException("当前商品抢购活动已经结束");
        }
        //根据商品Id 校验库存
        Stock stock = checkStock(id);
        //更新库存
        updateStock(stock);
        //创建订单
        return createOrder(stock);
    }

    @Override
    public String getMd5(Integer id, Integer userid) {
        //检验用户的合法性
        User user =userDAO.findById(userid);
        if(user==null){
            throw new RuntimeException("用户不存在");
        }
        log.info("用户信息：[{}]",user.toString());

        //检验商品的合法性
        Stock stock = stockDAO.checkStock(id);
        if(stock == null){
            throw new RuntimeException("商品信息不合法！");
        }
        log.info("商品信息：[{}]",stock.toString());

        //生成hashkey
        String hashKey = "KEY_"+userid+"_"+id;
        //生成md5
        String key = DigestUtils.md5DigestAsHex((userid+id+"!@#$%^&*").getBytes());
        stringRedisTemplate.opsForValue().set(hashKey,key,3600, TimeUnit.SECONDS);
        log.info("Redis写入：[{}] [{}]",hashKey,key);
        return key;
    }

    @Override
    public int kill(Integer id, Integer userid, String md5) {
        //检验redis中秒杀商品是否超时
        /*if(!stringRedisTemplate.hasKey("kill"+id)){
            throw new RuntimeException("当前商品抢购活动已经结束");
        }*/
        //先验证签名
        String hashKey = "KEY_"+userid+"_"+id;

        String s = stringRedisTemplate.opsForValue().get(hashKey);
        if(s==null) throw new RuntimeException("没有携带验证签名，请求不合法");
        if (!s.equals(md5)) {
            throw new RuntimeException("当前请求数据不合法！！！");
        }
        //根据商品Id 校验库存
        Stock stock = checkStock(id);
        //更新库存
        updateStock(stock);
        //创建订单
        return createOrder(stock);
    }

    //校验库存
    private Stock checkStock(Integer id){
        Stock stock = stockDAO.checkStock(id);
        if(stock.getSale().equals(stock.getCount())){
            throw new RuntimeException("库存不足");
        }
        return stock;
    }

    //扣除库存
    private void updateStock(Stock stock){
        //在sql层面完成销量的+1以及版本号的+1 并且根据商品id和版本号同时查询更新的商品
        stock.setSale(stock.getSale()+1);
        int updateRows = stockDAO.updateSale(stock);
        if(updateRows == 0){
            throw new RuntimeException("抢购失败，请重试！！！");
        }
    }

    //创建订单
    private Integer createOrder(Stock stock){
        //创建订单
        Order order = new Order();
        order.setSid(stock.getId()).setName(stock.getName()).setCreateDate(new Date());
        orderDAO.createOrder(order);
        return order.getId();
    }
}
